// provider.on("pending", listener)
import { ethers, utils} from "ethers";

///////////////////////////////////////////// 1. 创建provider和wallet，监听事件时候推荐用wss连接而不是http 
/// WebSocket Provider，更持久的监听交易, 因此，我们需要将url换成wss的
console.log("\n1. 连接 wss RPC")
// 准备 alchemy API 可以参考https://github.com/AmazingAng/WTFSolidity/blob/main/Topics/Tools/TOOL04_Alchemy/readme.md
const ALCHEMY_MAINNET_WSSURL = 'wss://eth-mainnet.g.alchemy.com/v2/oKmOQKbneVkxgHZfibs-iFhIlIAl6HDN';
const provider = new ethers.providers.WebSocketProvider(ALCHEMY_MAINNET_WSSURL);
let network = provider.getNetwork()
// network.then(res => console.log(`[${(new Date).toLocaleTimeString()}] 连接到 chain ID ${res.chainId}`));

console.log("\n2. 限制调用rpc接口速率")
///////////////////////////////////////////// 2. 限制访问rpc速率，不然调用频率会超出限制，报错。
/////因为mempool中的未决交易很多，每秒上百个，很容易达到免费rpc节点的请求上限，因此我们需要用throttle限制请求频率
function throttle(fn, delay) {
    let timer;
    return function(){
        if(!timer) {
            fn.apply(this, arguments)
            timer = setTimeout(()=>{
                clearTimeout(timer)
                timer = null
            },delay)
        }
    }
}

const main = async () => {
    let i = 0;
    ///////////////////////////////////////////// 3. 监听pending交易，获取txHash, 并打印交易哈希。
    console.log("\n3. 监听pending交易，打印txHash。")
    provider.on("pending", async (txHash) => {
        if (txHash && i < 10) {
            // 打印txHash
            console.log(`[${(new Date).toLocaleTimeString()}] 3. 监听Pending交易 ${i}: ${txHash} \r`);
            i++
            }
    });

    ///////////////////////////////////////////// 4. 监听pending交易，并获取交易详情
    //通过未决交易的哈希，获取交易详情。我们看到交易还未上链，它的blockHash，blockNumber，和transactionIndex都为空。
    //但是我们可以获取到交易的发送者地址from，燃料费gasPrice，目标地址to，发送的以太数额value，发送数据data等等信息。
    ///机器人就是利用这些信息进行MEV挖掘的。
    console.log("\n4. 监听pending交易，获取txHash，并输出交易详情。")
    let j = 0
    provider.on("pending", throttle(async (txHash) => {
        if (txHash && i >= 10) {
            // 获取tx详情
            let tx = await provider.getTransaction(txHash);
            console.log(`\n[${(new Date).toLocaleTimeString()}] 4. 监听Pending交易 ${j}: ${txHash} \r`);
            console.log(tx);
            j++
            }
    }, 1000));
};

main()

